#include "GUIConveyor.h"

GUIConveyor::GUIConveyor(int startX, int startY, const ConveyorType conveyorType)
	: conveyorType(conveyorType), GUIBase()
{
	switch (conveyorType)
	{
	case Conveyor_In:
		loadImage("Resources/Sprites/Conveyor/Conveyor.png");
		conveyorLines = new QGraphicsPixmapItem(QPixmap("Resources/Sprites/Conveyor/ConveyorDownLines.png"));
		this->setMovementSpeed(5.0);
		break;
	case Conveyor_OutGood:
		loadImage("Resources/Sprites/Conveyor/ConveyorGood.png");
		conveyorLines = new QGraphicsPixmapItem(QPixmap("Resources/Sprites/Conveyor/ConveyorUpLines.png"));
		this->setMovementSpeed(5.0);
		break;
	case Conveyor_OutBad:
		loadImage("Resources/Sprites/Conveyor/ConveyorBad.png");
		conveyorLines = new QGraphicsPixmapItem(QPixmap("Resources/Sprites/Conveyor/ConveyorUpLines.png"));
		this->setMovementSpeed(5.0);
		break;
	}

	this->setX(startX);
	this->setY(startY);
	this->setZValue(ZVALUE_CONVEYOR);

	conveyorLines->setPos(startX, startY);
	conveyorLines->setZValue(ZVALUE_CONVEYORLINES);
	factoryScene->addItem(conveyorLines);

	laneMoving = true;

	broken = false;
	blackAndWhite = false;


	kitWidth = -1;
	kitHeight = -1;
}

GUIConveyor::~GUIConveyor()
{
}

void GUIConveyor::DoCreateKit(KitRecipe* recipe)
{
	kitRecipes.push_back(recipe);
	laneMoving = true;
}

void GUIConveyor::DoSendKitOut(Kit* kit)
{
	kits.push_back(kit);
	//kit->rotateInstantlyTo(90);
	//kit->moveInstantlyTo(x() + kit->boundingRect().height() + KIT_X_OFFSET,  y() + this->boundingRect().height() - kit->boundingRect().width());
	laneMoving = true;
	//kit->setPos(QPoint(x() + kit->boundingRect().height(),  y() + this->boundingRect().height() - kit->boundingRect().width()));
	//kit->rotationSpeed = 100000;
	//kit->rotateOverTime(90, true);
	if(conveyorType==Conveyor_OutBad){
		kit->rotateInstantlyTo(270);
		kit->moveInstantlyTo(x()+10, kit->y());
	}
}

void GUIConveyor::DoKitTaken()
{
	kits.pop_front();
	laneMoving = true;
}

void GUIConveyor::DoPurgeKit() {
	if (!kits.empty())
	{
		kits.front()->deleteLater();
		kits.pop_front();
		laneMoving = true;
	}
}

void GUIConveyor::setAgent(ConveyorAgent* agent)
{
	this->agent = agent;
	this->setGUIBaseAgent(agent);
}

void GUIConveyor::advance(int phase)
{
	if (!kitRecipes.empty())
	{
		// Create new kit to send down.
		Kit* newKit = new Kit(this->x(), this->y());

		if (kits.empty()) // Free conveyor just throw it at the top.
		{
			newKit->setPos(this->x() + getKitHeight() + KIT_X_OFFSET, this->y() - getKitWidth());
		}
		else // Base the location of the new kit off of the newest kit on the conveyor (shouldn't overlap)
		{
			Kit* newestKit = kits.back();
			if (newestKit->y() > DISTANCE_BETWEEN_KITS)
				newKit->setPos(this->x() + getKitHeight() + KIT_X_OFFSET, this->y() - getKitWidth());
			else
				newKit->setPos(this->x() + getKitHeight() + KIT_X_OFFSET, newestKit->y() - getKitWidth() - DISTANCE_BETWEEN_KITS);
		}
		newKit->setRotation(90);
		kits.push_back(newKit);

		for (int i = 0; i < kitRecipes.front()->partsNeeded.size(); i++)
		{
			newKit->partTypesNeeded.push_back(kitRecipes.front()->partsNeeded[i]);
		}
		kitRecipes.pop_front();
	}

	// If it's broken, it shouldn't move.
	if (broken)
		return;

	// No kits, no movement.
	if (kits.empty())
		return;

	// Delete all outbound kits if off the screen.
	if (conveyorType == Conveyor_OutGood || conveyorType == Conveyor_OutBad)
	{
		if (kits.front()->y() - this->y() < -getKitWidth()) // If there's a kit at the end of the conveyor, stop moving.
		{
			kits.front()->deleteLater();
			kits.pop_front();
			return;
		}
	}

	// Kit is waiting at the end, so don't move.
	if (!laneMoving)
		return;
	
	if(phase==1)
	{
		switch(conveyorType)
		{
		case Conveyor_In:
			for(std::list<Kit*>::iterator it = kits.begin(); it != kits.end(); it++)
			{
				(*it)->setY(((*it)->y()) + this->speed);
			}

			this->conveyorLines->setY((conveyorLines->y()) + this->speed);
			if (conveyorLines->y() - this->y() > 52)
				conveyorLines->setY(this->y());

			if (qAbs(kits.front()->y() + kits.front()->boundingRect().width()) > (y() +LANE_LENGTH)) // If there's a kit at the end of the conveyor, stop moving.
			{
				agent->msgKitEndOfConveyor(kits.front());
				laneMoving = false;
			}

			break;
		case Conveyor_OutGood:
		case Conveyor_OutBad:
			for(std::list<Kit*>::iterator it = kits.begin(); it != kits.end(); it++)
			{
				(*it)->setY(((*it)->y()) - this->speed);
			}

			this->conveyorLines->setY((conveyorLines->y()) - this->speed);
			if (this->y() - conveyorLines->y() > 52)
				conveyorLines->setY(this->y());

			break;
		}
	}
}

// WHY WAS THIS HARD CODED? WHY? PLEASE TELL ME WHY?! HOW CAN YOU JUST ASSUME COORDINATES LIKE THAT? ANYWAY I CHANGED IT

//QPoint GUIConveyor::getPickUpKitPosition()
//{
//	return QPoint(200, 200);
//}
//
//QPoint GUIConveyor::getDropOffKitPosition()
//{
//	return QPoint(200, 200);
//}

QPoint GUIConveyor::getPickUpKitPosition()
{
	return QPoint(x(), y() + this->boundingRect().height() - getKitWidth()/2);
}

QPoint GUIConveyor::getDropOffKitPosition()
{
	return QPoint(x()+20,  y() + this->boundingRect().height() - getKitWidth()/2);
}

int GUIConveyor::getKitWidth() {
	if(kitWidth <= 0) {
		if(this->kits.size() > 0) {
			kitWidth = kits.front()->boundingRect().width();
			kitHeight = kits.front()->boundingRect().height();
		} else {
			Kit* k = new Kit(0,0, scene());
			kitWidth = k->boundingRect().width();
			kitHeight = k->boundingRect().height();
			scene()->removeItem(k);
		}
	} 
	return kitWidth;
}

int GUIConveyor::getKitHeight() {
	if(kitWidth <= 0) {
		if(this->kits.size() > 0) {
			kitWidth = kits.front()->boundingRect().width();
			kitHeight = kits.front()->boundingRect().height();
		} else {
			Kit* k = new Kit(0,0, scene());
			kitWidth = k->boundingRect().width();
			kitHeight = k->boundingRect().height();
			scene()->removeItem(k);
		}
	} 
	return kitHeight;
}

void GUIConveyor::DoBreak()
{
	qDebug("wtf");
	broken = true;
	blackAndWhite = true;
}

void GUIConveyor::DoFix()
{
	qDebug("conveyor fixed");
	broken = false;
	blackAndWhite = false;
}
